/***************************************************************************
 *   Copyright (C) 2010 by Peter Hatina                                    *
 *   email: phatina (at) gmail.com                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License           *
 *   version 2.1 as published by the Free Software Foundation              *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Lesser General Public License for more details.                   *
 *   http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.               *
 ***************************************************************************/

#include "graph.h"
#include "csvminer.h"
#include "settings.h"
#include <QPainter>

#include <iostream>

const int AXE_TIME_SPACE = 50;

Graph::Graph(QWidget *parent):
	QWidget(parent),
	m_scale(true),
	m_grid(true),
	m_margin_left(40),
	m_margin_bottom(80),
	m_margin_top(10),
	m_margin_right(40)
{
}

Graph::~Graph()
{
}

void Graph::showScale(bool show)
{
	if (m_scale == show)
		return;

	m_scale = show;
	update();
}

void Graph::showGrid(bool show)
{
	if (m_grid == show)
		return;

	m_grid = show;
	update();
}

QPoint Graph::getGridPos(int x, int y) const
{
	int cnt = m_data.count() - 1;
	if (cnt == 0)
		cnt = 1;

	float step_x = 1.0 * (width() - m_margin_left - m_margin_right) / cnt;
	float step_y = 1.0 * (height() - m_margin_top - m_margin_bottom) / 10;

	return QPoint(m_margin_left + x * step_x, m_margin_top + (10 - y) * step_y);
}

int Graph::getGridX(int x) const
{
	int cnt = m_data.count() - 1;
	if (cnt == 0)
		cnt = 1;

	float step_x = 1.0 * (width() - m_margin_left - m_margin_right) / cnt;
	return m_margin_left + x * step_x;
}

void Graph::load()
{
	Settings settings;
	settings.loadAppSettings();

	CsvMiner miner;
	miner.load(settings.logFile());
	m_data = miner.data();

	repaint();

//	for (int i = 0; i < m_data.count(); i++)
//	{
//		std::cout << m_data[i].dateTime().toString("hh:mm:ss").toStdString() << "\n";
//		std::cout << m_data[i].level() << "\n";
//		if (m_data[i].ac())
//			std::cout << "pripojeny\n";
//		else
//			std::cout << "nepripojeny\n";
//	}

	setMinimumWidth(m_data.count() * AXE_TIME_SPACE);
	//setMaximumWidth(minimumWidth());
}

void Graph::show()
{
	load();
	QWidget::show();
}

void Graph::paintEvent(QPaintEvent *ev)
{
	Q_UNUSED(ev);

	QPainter painter(this);
	QFontMetrics font_metrics = painter.fontMetrics();

	//draw axes
	painter.drawLine(m_margin_left, m_margin_top, m_margin_left, height() - m_margin_bottom);
	painter.drawLine(m_margin_left, height() - m_margin_bottom,
		width() - m_margin_right, height() - m_margin_bottom);

	//draw scale markers
	if (m_scale)
	{
		//vertical scale + titles
		for (int i = 1; i < 11; i++)
		{
			QString label = QString("%1").arg(i * 10);

			QPoint p = getGridPos(0, i);
			painter.drawLine(p.x() - 2, p.y(), p.x() + 2, p.y());
			painter.drawText(p.x() - 10 - font_metrics.width(label),
				p.y() + font_metrics.height() / 2,
				label);
		}

		//horizontal scale
		for (int i = 0; i < m_data.count(); i++)
		{
			QDateTime date_time = m_data[i].dateTime();
			QString label_date = date_time.toString("dd.MM.yyyy");
			QString label_time = date_time.toString("hh:mm:ss");

			QPoint p = getGridPos(i, 0);

			painter.drawLine(p.x(), p.y() + 2, p.x(), p.y() - 2);

			if (i % 2)
				p.setY(5 + p.y() + font_metrics.height() * 2);

			painter.drawText(p.x() - font_metrics.width(label_date) / 2,
				p.y() + 5 + font_metrics.height(),
				label_date);

			painter.drawText(p.x() - font_metrics.width(label_time) / 2,
				p.y() + 5 + font_metrics.height() * 2,
				label_time);
		}
	}

	//grid
	if (m_grid)
	{
		QPen old_pen = painter.pen();
		QPen new_pen;
		new_pen.setColor(QColor(225, 225, 225));
		new_pen.setStyle(Qt::DashLine);
		painter.setPen(new_pen);

		const int max_x = m_data.count() - 1;
		const int max_y = height() - m_margin_top - m_margin_bottom;

		for (int i = 1; i < 10; i++)
		{
			QPoint p1 = getGridPos(0, i);
			QPoint p2 = getGridPos(max_x, i);
			painter.drawLine(p1.x() + 2, p1.y(), p2.x(), p2.y());
		}

		const int cnt = m_data.count();
		for (int i = 1; i < cnt; i++)
		{
			QPoint p1(getGridX(i), m_margin_top);
			QPoint p2(getGridX(i), max_y);
			painter.drawLine(p1.x(), p1.y() - 2, p2.x(), p2.y());
		}

		painter.setPen(old_pen);
	}

	//graph values
	const int cnt = m_data.count();
	const int h = height() - m_margin_top - m_margin_bottom;
	const int circle_r = 2;
	QPoint p1(getGridX(0), (h + m_margin_top) - (h * m_data[0].level() / 100.0));
	QPoint p2;

	painter.drawEllipse(p1, circle_r, circle_r);
	for (int i = 1; i < cnt; i++)
	{
		p2.setX(getGridX(i));
		p2.setY((h + m_margin_top) - (h * m_data[i].level() / 100.0));

		painter.drawLine(p1, p2);
		painter.drawEllipse(p2, circle_r, circle_r);

		//draw value below the circle
		QString str_value = QString("%1").arg(m_data[i].level());
		QPen old_pen = painter.pen();
		QPen new_pen;
		new_pen.setColor(QColor(30, 140, 100));
		painter.setPen(new_pen);
		QFont old_font = painter.font();
		QFont new_font;
		new_font.setBold(true);
		painter.setFont(new_font);

		//painter.rotate(90.0);
		painter.drawText(p2.x() - painter.fontMetrics().width(str_value) / 2,
			p2.y() + painter.fontMetrics().height() + 5,
			str_value);


		painter.setPen(old_pen);
		painter.setFont(old_font);

		p1 = p2;
	}
}
